package com.apes.framework.plugin.workflow.lib;

import com.alibaba.fastjson.JSON;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.workflow.FlowableEngine;
import com.apes.framework.plugin.workflow.parser.model.Node;
import com.apes.framework.plugin.workflow.parser.model.Workflow;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.Tools;
import com.apes.scm.rbac.model.User;
import com.apestech.framework.util.StringUtil;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;

import java.util.*;

import static com.apes.framework.plugin.workflow.parser.model.Workflow.getWorkflow;

/**
 * 相关工具类
 *
 * @author hup
 * @create 2018-07-24-9:41
 */
public class OAUtil {

    /**
     * 功能：mapping
     *
     * @param node
     * @param variables
     * @return
     */
    public static Map mapping(Node node, Map variables) {
        Map m = null;
        if (node != null) m = node.convert(variables);
        if (m == null) m = new HashMap();
        return m;
    }

    /**
     * 功能：获取任务的候选人列表
     */
    public static List<String> getTaskCandidate(ProcessEngine engine, String taskId) {
        List<String> users = new ArrayList<>();
        List identityLinkList = engine.getTaskService().getIdentityLinksForTask(taskId);
        if (identityLinkList == null) return users;
        for (Iterator iterator = identityLinkList.iterator(); iterator.hasNext(); ) {
            IdentityLink identityLink = (IdentityLink) iterator.next();
            if (identityLink.getUserId() != null) {
                users.add(identityLink.getUserId());
            }
        }
        return users;
    }

    /**
     * 功能：获取任务的受理人
     *
     * @param task
     * @return
     */
    public static String getTaskAssignee(Task task) {
        if (!Tools.isNull(task.getAssignee())) return task.getAssignee();
        return null;
    }

    /**
     * 功能：content
     *
     * @param node
     * @param variables
     * @return
     */
    public static Map content(Node node, Map variables) {
        Map m = null;
        if (node != null) m = node.content(variables);
        if (m == null) m = new HashMap();
        return m;
    }

    //gatewayList= getExclusiveGateway(task.getProcessInstanceId())
    public static Map convertTask(ProcessEngine engine, Task task, String wf_content, List gatewayList) {
        Map m = new HashMap();
        m.put("taskId", task.getId());
        m.put("taskName", task.getName());
        Map content = new HashMap();

        Object o = getVariable(engine, task.getId(), wf_content);
        if (!Tools.isNull(o)) {
            content.putAll(JSON.parseObject((String) o));
        }

        m.put("content", content);
        m.put("createTime", task.getCreateTime());

        String processDefinitionKey = null;
        Object pi = findProcessInstance(engine, task.getProcessInstanceId());
        if (pi instanceof HistoricProcessInstance) {
            m.put("processDefinitionName", ((HistoricProcessInstance) pi).getProcessDefinitionName());
            m.put("businessKey", ((HistoricProcessInstance) pi).getBusinessKey());
            processDefinitionKey = ((HistoricProcessInstance) pi).getProcessDefinitionKey();
        } else if (pi instanceof ProcessInstance) {
            m.put("processDefinitionName", ((ProcessInstance) pi).getProcessDefinitionName());
            m.put("businessKey", ((ProcessInstance) pi).getBusinessKey());
            processDefinitionKey = ((ProcessInstance) pi).getProcessDefinitionKey();
            m.put("exclusiveGateway",gatewayList);
        }
        Workflow wf = getWorkflow(processDefinitionKey);

        Node node = wf.getTaskNode(task.getTaskDefinitionKey());
        if (node != null && node.getForm()!=null) {
            m.put("formId", node.getForm().getId());
            m.put("api", node.getForm().getApi());
            m.put("fields", node.getFields());
            m.put("auth", node.getAuth());
            m.put("editable", node.isEditable());

            // 抄送流程发起人
            if (node.isCarbonCopy()) {
                List<Task> list = engine.getTaskService().createTaskQuery().taskId(task.getId()).list();
                if (list != null && list.size() > 0) {
                    String processInitiator = (String) engine.getTaskService().getVariable(task.getId(), "processInitiator");
                    List<Object> users = SpringManager.getBean(FlowableEngine.class).sendSynEvent("event:aut.user.findOne", MapUtil.mapper("id", Integer.parseInt(processInitiator)));
                    if (users != null && users.size() > 0 && users.get(0) != null) {
                        m.put("carbonCopy", MapUtil.mapper(
                                "id", ((User) users.get(0)).getId(),
                                "name", ((User) users.get(0)).getName()
                                )
                        );
                    }
                }
            }
        }
        return m;
    }

    public static Object getVariable(ProcessEngine engine, String taskId, String variableName) {
        Object result = null;
        TaskInfo taskInfo = findTaskInfoById(engine, taskId);
        if (taskInfo instanceof Task) {
            result = engine.getTaskService().getVariable(taskId, variableName);
            if (result == null) result = engine.getTaskService().getVariableLocal(taskId, variableName);
        } else {
            result = taskInfo.getProcessVariables().get(variableName);
            if (result == null) result = taskInfo.getTaskLocalVariables().get(variableName);
        }
        return result;
    }

    /**
     * 根据任务ID获得任务信息
     *
     * @param taskId
     * @return
     */
    public static TaskInfo findTaskInfoById(ProcessEngine engine, String taskId) {
        TaskInfo taskInfo = engine.getTaskService().createTaskQuery().taskId(taskId).singleResult();
        if (taskInfo == null) {
            taskInfo = engine.getHistoryService().createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
            if (taskInfo == null) {
                throw new RuntimeException("任务实例未找到!");
            }
        }
        return taskInfo;
    }

    /**
     * 功能：获取流程下步待执行任务
     *
     * @param processInstanceId
     * @return
     */
    public static Task getNextTask(ProcessEngine engine, String processInstanceId) {
        return engine.getTaskService().createTaskQuery().processInstanceId(processInstanceId).singleResult();
    }

    public static Object findProcessInstance(ProcessEngine engine, String processInstanceId) {
        Object processInstance = engine.getRuntimeService().createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance == null) {
            processInstance = engine.getHistoryService().createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            if (processInstance == null) {
                throw new RuntimeException("流程实例未找到!");
            }
        }
        return processInstance;
    }

    public static List<String> getTaskUser(ProcessEngine engine, Task task) {
        List<String> users = new ArrayList<>();
        if (StringUtil.isNotEmpty(task.getAssignee())) {
            users.add(task.getAssignee());
        } else {
            users.addAll(getTaskCandidate(engine, task.getId()));
        }
        return users;
    }


}
